﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management;
using System.Net;
using System.DirectoryServices;
using System.Data.OleDb;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.IO;
using System.DirectoryServices.ActiveDirectory;
using ActiveDs;

namespace Canwest.Broadcasting.Windows.Forms.RenameMachines
{
    public struct LastLogonInfo
    {
        public String m_username;
        public DateTime m_lastLogon;
        public String m_lastLogonString;
        public Boolean m_enabled;
        public String m_errorMsg;
        public String m_errorDump;
    }


    public class WMIWrapper
    {

        private String m_domain_admin = null;
        private String m_domain_admin_password = null;
        private const String m_defaultAdQuery = "SELECT physicalDeliveryOfficeName, sAMAccountName, company, department, streetAddress FROM 'LDAP://OU=Toronto,OU=Ontario,DC=ca,DC=canwest,DC=com' WHERE objectClass='User'AND objectCategory='Person' AND sAMAccountName= '<Username>'";
        private String m_department = null;
        private String m_location = null;
        private String m_floor = null;
        private String m_accountName = null;
        private String m_PcAdministrator = null;
        private String m_PcAdministratorPassword = null;
        private String m_locationOfNetdomScript = null;
        private String m_error_msg = null;
        private String m_stacktrace = null;

        //private String m_lastUser = null;
        private List<LastLogonInfo> m_lastLogons = new List<LastLogonInfo>();
        private DateTime m_lastLogonDate;

        private String m_toolAdminAccount = null;
        private String m_toolAdminPassword = null;

        public String Username
        {
            get
            {
                return m_domain_admin;
            }
            set
            {
                m_domain_admin = value;
            }
        }

        public String Password
        {
            get
            {
                return m_domain_admin_password;
            }
            set
            {
                m_domain_admin_password = value;
            }
        }

        public String PC_Administrator
        {
            get
            {
                return m_PcAdministrator;
            }
            set
            {
                m_PcAdministrator = value;
            }
        }

        public String PC_Administrator_Password
        {
            get
            {
                return m_PcAdministratorPassword;
            }
            set
            {
                m_PcAdministratorPassword = value;
            }
        }

        public String Department
        {
            get
            {
                return m_department;
            }
        }

        public String Location
        {
            get
            {
                return m_location;
            }
        }

        public String LocationOfNetdomScript
        {
            get
            {
                return m_locationOfNetdomScript;
            }
            set
            {
                m_locationOfNetdomScript = value;
            }
        }

        public String ErrorMessage
        {
            get
            {
                return m_error_msg;
            }
        }

        public String ErrorStackTrace
        {
            get
            {
                return m_stacktrace;
            }
        }

        public List<LastLogonInfo> LastLogons
        {
            get
            {
                return m_lastLogons;
            }
        }

        public String ToolAdminUser
        {
            get
            {
                return m_toolAdminAccount;
            }
            set
            {
                m_toolAdminAccount = value;
            }
        }

        public String ToolAdminPassword
        {
            get
            {
                return m_toolAdminPassword;
            }
            set
            {
                m_toolAdminPassword = value;
            }
        }


        public Boolean renameRemoteHost(String oldName, String newName, String domain)
        {


            Boolean renameADObjOK = renameActiveDirectoryObject(oldName, newName);

            if (renameADObjOK)
            {
                Boolean renamePCOK = renameRemotePC(oldName, newName, domain);

                if (!renamePCOK)
                {
                    renameActiveDirectoryObject(newName, oldName);
                }
                else
                {
                    return true;
                }

            }

            return false;
            
        }

        public Boolean renameActiveDirectoryObject(String oldName, String newName)
        {
            Boolean rc = true;
            String objectDn = null;
            objectDn = "CN=" + oldName + ",OU=Development Testing,OU=Users,OU=Bloor,OU=CW Media,OU=Toronto,OU=Ontario,DC=ca,DC=canwest,DC=com";
            //objectDn = "CN=" + oldName + ",OU=CW Media,DC=ca,DC=canwest,DC=com";
            DirectoryEntry remotePC = new DirectoryEntry("LDAP://" + objectDn);
            remotePC.Username = m_domain_admin;
            remotePC.Password = m_domain_admin_password;

            try
            {
                remotePC.Rename(newName);
            }
            catch (Exception e)
            {
                //rc = false;
                m_error_msg += "Renaming AD object error: " + e.Message;
                m_stacktrace += "Renaming AD object dump: " + e.StackTrace;
                                
            }

            remotePC.CommitChanges();

            return rc;

        }

        public Boolean renameRemotePC(String oldName, String newName, String domain)
        {

            Boolean rc = true;

            try
            {

                ManagementPath remoteControlObject = new ManagementPath();
                remoteControlObject.ClassName = "Win32_ComputerSystem";
                remoteControlObject.Server = oldName;
                remoteControlObject.Path = oldName + "\\root\\cimv2:Win32_ComputerSystem.Name='" + oldName + "'";
                remoteControlObject.NamespacePath = "\\\\" + oldName + "\\root\\cimv2";

                ConnectionOptions conn = new ConnectionOptions();
                conn.Authentication = AuthenticationLevel.PacketPrivacy;
                conn.Username = oldName + "\\" + m_PcAdministrator;
                conn.Password = m_PcAdministratorPassword;

                ManagementScope remoteScope = new ManagementScope(remoteControlObject, conn);

                ManagementObject remoteSystem = new ManagementObject(remoteScope, remoteControlObject, null);
                
                ManagementBaseObject outParams;

                ManagementBaseObject unjoinFromDomain = remoteSystem.GetMethodParameters("UnjoinDomainOrWorkgroup");
                unjoinFromDomain.SetPropertyValue("Password", m_domain_admin_password);
                unjoinFromDomain.SetPropertyValue("UserName", m_domain_admin);
                outParams = remoteSystem.InvokeMethod("UnjoinDomainOrWorkgroup", unjoinFromDomain, null);                

                ManagementBaseObject newRemoteSystemName = remoteSystem.GetMethodParameters("Rename");
                InvokeMethodOptions methodOptions = new InvokeMethodOptions();

                newRemoteSystemName.SetPropertyValue("Name", newName);
                newRemoteSystemName.SetPropertyValue("UserName", m_PcAdministrator);
                newRemoteSystemName.SetPropertyValue("Password", m_PcAdministratorPassword);

                methodOptions.Timeout = new TimeSpan(0, 10, 0);
                outParams = remoteSystem.InvokeMethod("Rename", newRemoteSystemName, null);

                ManagementBaseObject joinFromDomain = remoteSystem.GetMethodParameters("JoinDomainOrWorkgroup");
                joinFromDomain.SetPropertyValue("Name", domain);
                joinFromDomain.SetPropertyValue("Password", m_domain_admin_password);
                joinFromDomain.SetPropertyValue("UserName", m_domain_admin);
                joinFromDomain.SetPropertyValue("FJoinOptions", 1);
                outParams = remoteSystem.InvokeMethod("JoinDomainOrWorkgroup", joinFromDomain, null);                

            }
            catch (ManagementException MgEx)
            {
                String mgs = MgEx.Message;
                String coredump = MgEx.StackTrace;
                m_error_msg += "\nRenaming PC Error: " + mgs;
                m_stacktrace += "\nRenaming PC dump: " + coredump;
                //rc = false;
            }
            catch (Exception e)
            {
                String mgs = e.Message;
                String coredump = e.StackTrace;
                m_error_msg += "\nRenaming PC Error: " + mgs;
                m_stacktrace += "\nRenaming PC dump: " + coredump;
                //rc = false;
            }

            return rc;

        }

        public String getComputerName(String p_username, String oDepartmentName, String oLocationName, String departmentAcro, String locationAcro)
        {
            //DirectoryEntry dir = new DirectoryEntry("LDAP://rootDse");
            //DirectorySearcher searcher = new DirectorySearcher(dir);

            if (String.IsNullOrEmpty(p_username))
            {
                return null;
            }
            if (String.IsNullOrEmpty(oDepartmentName))
            {
                return null;
            }
            if (String.IsNullOrEmpty(oLocationName))
            {
                return null;
            }
            if (String.IsNullOrEmpty(departmentAcro))
            {
                return null;
            }
            if (String.IsNullOrEmpty(locationAcro))
            {
                return null;
            }

            String userQuery = m_defaultAdQuery.Replace("<Username>", p_username);

            OleDbConnection conn = new OleDbConnection();
            conn.ConnectionString = "Provider=ADsDSOObject;";
            conn.Open();
            OleDbCommand cmd = new OleDbCommand(userQuery, conn);
            OleDbDataReader dr = null;
            dr = cmd.ExecuteReader();
            dr.Read();
            
            String streetAddress = dr["streetAddress"].ToString();

            if (streetAddress.ToLower().Contains(oLocationName.ToLower()))
            {
                m_location = locationAcro.ToUpper();
            }
            
            String department = dr["department"].ToString();
            String company = dr["company"].ToString();

            if (department.ToLower().Contains(oDepartmentName.ToLower()))
            {
                m_department = departmentAcro.ToUpper();
            }
            if (company.ToLower().Contains(oDepartmentName.ToLower()))
            {
                m_department = departmentAcro.ToUpper();
            }

            String physicalDeliveryOfficeName = null;
            physicalDeliveryOfficeName = dr["physicalDeliveryOfficeName"].ToString();
            if (!String.IsNullOrEmpty(physicalDeliveryOfficeName))
            {
                if (physicalDeliveryOfficeName.Length >= 2)
                {
                    Regex numericalPattern = new Regex("[^0-9]");

                    if (numericalPattern.IsMatch(physicalDeliveryOfficeName.Substring(1, 2)))
                    {
                        m_floor = physicalDeliveryOfficeName.Substring(1, 2);
                    }
                }
            }

            m_accountName = dr["sAMAccountName"].ToString();

            String newComputerName = m_accountName + m_department + m_floor + m_location;

            if (!String.IsNullOrEmpty(newComputerName))
            {
                newComputerName = newComputerName.ToUpper();
            }

            return newComputerName;

        }

        //public Boolean renameRemoteHost_ThreadPoolCallback(String pcAdministrator, String pcAdministratorPassword, String domainAdministrator, String domainAdministratorPassword, String domain, String oldName, String newName)
        //{
        //    WMIWrapper wrapper = new WMIWrapper();
        //    wrapper.PC_Administrator = pcAdministrator;
        //    wrapper.PC_Administrator_Password = pcAdministratorPassword;
        //    wrapper.Username = domainAdministrator;
        //    wrapper.Password = domainAdministratorPassword;
        //    return wrapper.renameRemoteHost(oldName, newName, domain);

        //}

        public Boolean renameRemoteHost_ThreadPoolCallback(String pcAdministrator, String pcAdministratorPassword, String domainAdministrator, String domainAdministratorPassword, String domain, String oldName, String newName)
        {
            WMIWrapper wrapper = new WMIWrapper();
            wrapper.PC_Administrator = pcAdministrator;
            wrapper.PC_Administrator_Password = pcAdministratorPassword;
            wrapper.Username = domainAdministrator;
            wrapper.Password = domainAdministratorPassword;
            return wrapper.renameRemoteHost(oldName, newName, domain);

        }

        public Boolean addLocalAdministrator(String machineName, String pcAdministrator, String pcAdministratorPassword)
        {
            //return addUserByProcess(machineName, "CW_Synch_Admin", "March102009", pcAdministrator, pcAdministratorPassword);
            return false;
        }

        public Boolean addUserByDirectoryServices(String machineName, String pcAdministrator, String pcAdministratorPassword)
        {
            Boolean rc = true;

            try
            {
                String connString = "WinNT://" + machineName;

                using (DirectoryEntry de = new DirectoryEntry(connString, pcAdministrator, pcAdministratorPassword))
                {

                    //if (de.Children.Find(m_PcAdministrator) != null)
                    //{
                    //    de.Close();
                    //    de.Dispose();
                    //    return true;
                    //}

                    DirectoryEntry user = de.Children.Add(m_PcAdministrator, "user");
                    user.Invoke("SetPassword", new Object[] { m_PcAdministratorPassword });
                    user.CommitChanges();

                    de.RefreshCache();

                    DirectoryEntry adminGroup = de.Children.Find("Administrators", "group");
                    if (null != adminGroup)
                    {
                        adminGroup.Invoke("Add", new Object[] { user.Path.ToString() });
                    }

                    de.Close();
                    de.Dispose();

                }

                rc = true;
                

            }
            catch (Exception e)
            {
                String msg = e.Message;
                m_error_msg += "Adding local user error: " + msg;
                String stacktrace = e.StackTrace;
                m_stacktrace += "\nAdding local user dump: " + stacktrace;
            }

            return rc;

        }


        public Boolean removeLocalAdministrator(String machineName, String pcAdministrator, String pcAdministratorPassword)
        {
            return removeUserByProcess(machineName, "CW_Synch_Admin", "March102009", pcAdministrator, pcAdministratorPassword);
        }

        protected Boolean addUserByProcess(String machineName, String username, String password, String administrator, String adminPassword)
        {
            Boolean rc = true;

            try
            {

      //          Process MyProc = new Process();
                
      //          MyProc.StartInfo.WorkingDirectory = @"C:\WINNT\SYSTEM32";
      //          MyProc.StartInfo.FileName = "net.exe";
      //          MyProc.StartInfo.UseShellExecute = false;
      //          MyProc.StartInfo.RedirectStandardError = true;
      //          MyProc.StartInfo.RedirectStandardInput = true;
      //          MyProc.StartInfo.RedirectStandardOutput = true;
      //          MyProc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;

      //          //MyProc.StartInfo.Arguments = @" user " + username + @" " + password + @" /ADD /ACTIVE:YES " +
      //          //  @"/EXPIRES:NEVER /FULLNAME:" + username + @" /HOMEDIR:""" +
      //          //  homedir + @""" /PASSWORDCHG:NO /PASSWORDREQ:YES";

      //          MyProc.StartInfo.Arguments = @" user " + username + @" " + password + @" /ADD /ACTIVE:YES " +
      //@"/EXPIRES:NEVER /FULLNAME:" + username + @" /PASSWORDCHG:NO /PASSWORDREQ:YES";

      //          MyProc.Start();
      //          MyProc.WaitForExit();
      //          MyProc.Close();


                ConnectionOptions connOps = new ConnectionOptions();
                connOps.Authentication = AuthenticationLevel.PacketPrivacy;
                connOps.Username = administrator;
                connOps.Password = adminPassword;
                ManagementPath machinePath = new ManagementPath("\\\\" + machineName + "\\root\\cimv2:Win32_Process");
                ManagementScope remoteScope = new ManagementScope(machinePath, connOps);
                remoteScope.Connect();

                ObjectGetOptions manageOps = new ObjectGetOptions();
                ManagementClass remoteClass = new ManagementClass(remoteScope, machinePath, manageOps);

                ManagementBaseObject inParams = remoteClass.GetMethodParameters("Create");
                String cmd = "net.exe user " + username + " " + password + " /ADD /ACTIVE:YES /EXPIRES:NEVER /FULLNAME:" + username + " /PASSWORDCHG:NO /PASSWORDREQ:YES";
                inParams.SetPropertyValue("CommandLine", cmd);
                inParams.SetPropertyValue("ExecutablePath", "C:\\WINNT\\SYSTEM32\\net.exe");
                ManagementBaseObject outParams = remoteClass.InvokeMethod("Create", inParams, null);

                cmd = "net.exe localgroup administrators " + username + " /add";
                inParams.SetPropertyValue("CommandLine", cmd);

                outParams = remoteClass.InvokeMethod("Create", inParams, null);



            }
            catch (Exception e)
            {
                rc = false;
            }

            return rc;
        }


        protected Boolean removeUserByProcess(String machineName, String username, String password, String administrator, String adminPassword)
        {
            Boolean rc = true;

            try
            {

                ConnectionOptions connOps = new ConnectionOptions();
                connOps.Authentication = AuthenticationLevel.PacketPrivacy;
                connOps.Username = administrator;
                connOps.Password = adminPassword;
                ManagementPath machinePath = new ManagementPath("\\" + machineName + "\\root\\cimv2:Win32_Process");
                ManagementScope remoteScope = new ManagementScope(machinePath, connOps);
                remoteScope.Connect();

                ObjectGetOptions manageOps = new ObjectGetOptions();
                ManagementClass remoteClass = new ManagementClass(remoteScope, machinePath, manageOps);

                ManagementBaseObject inParams = remoteClass.GetMethodParameters("Create");
                String cmd = "net.exe user " + username + " /DELETE";
                inParams.SetPropertyValue("CommandLine", cmd);
                inParams.SetPropertyValue("ExecutablePath", "C:\\WINNT\\SYSTEM32\\net.exe");
                ManagementBaseObject outParams = remoteClass.InvokeMethod("Create", inParams, null);


            }
            catch (Exception e)
            {
                rc = false;
            }

            return rc;


        }

        public void addUserByWin32(String servername, String username, String password)
        {
            Int32 rc = 0;
            USER_INFO_1 userinfo = new USER_INFO_1();
            userinfo.usri1_name = username;
            userinfo.usri1_password = password;
            userinfo.usri1_priv = 2;
            userinfo.usri1_home_dir = null;
            userinfo.usri1_comment = "Created by C# Win32 call.";
            userinfo.usri1_script_path = null;
            //userinfo.usri1_password_age = &H40;


            UInt32 rc1 = 0;

            rc1 = Win32Native.NetUserAdd(servername, 1, ref userinfo, 0);



        }

        /// <summary>
        /// This method can only be used on machines version XP SP3 and up
        /// </summary>
        /// <param name="hostname"></param>
        /// <param name="username"></param>
        /// <param name="password"></param>
        /// <param name="administrator"></param>
        /// <param name="administratorPassword"></param>
        public Boolean addUserByDirectoryServices(String hostname, String username, String password, String administrator, String administratorPassword)
        {


            Boolean rc = true;

            try
            {
                DirectoryEntry AD = new DirectoryEntry("WinNT://" + hostname + ",computer");
                AD.Username = administrator;
                AD.Password = administratorPassword;
                DirectoryEntry NewUser = AD.Children.Add(username, "user");
                NewUser.Invoke("SetPassword", new object[] { password });
                NewUser.Invoke("Put", new object[] { "Description", "For renaming computer only." });
                NewUser.CommitChanges();


                DirectoryEntry group;
                group = AD.Children.Find("Administrators", "group");
                if (null != group)
                {
                    group.Invoke("Add", new Object[] { NewUser.Path.ToString() });
                    group.CommitChanges();
                }

            }
            catch (Exception e)
            {
                rc = false;
            }

            return rc;


        }

        public Boolean renameMachineByDirectoryServices(String oldname, String newname, String administrator, String administratorPassword)
        {


            Boolean rc = true;

            try
            {
                DirectoryEntry machineNode = null;
                //machineNode = new DirectoryEntry("WinNT://" + oldname + ",computer");
                machineNode = new DirectoryEntry("WinNT://" + oldname);
                //machineNode = new DirectoryEntry("LDAP://CN=" + oldname + ",DC=ca,DC=canwest,DC=com");
                machineNode.Username = administrator;
                machineNode.Password = administratorPassword;
                machineNode.AuthenticationType = AuthenticationTypes.Secure;
                //machineNode.DeleteTree();
                machineNode.Rename(newname);
                //machineNode.Properties["CommonName"].Value = newname;
                machineNode.CommitChanges();

                
            }
            catch (Exception e)
            {
                String msg = e.Message;
                String stacktrace = e.StackTrace;
                rc = false;
            }

            return rc;


        }

        public Boolean renameMachineByNetdom(String oldname, String newname, String p_username, String p_password)
        {
            //Current settings work!

            Boolean rc = true;
            Process MyProc = new Process();

            try
            {

                MyProc.StartInfo.WorkingDirectory = @"C:\\Derrick\\RenamePCs";
                MyProc.StartInfo.FileName = "rename_netdom.bat";
                //MyProc.StartInfo.FileName = "cmd";
                MyProc.StartInfo.UseShellExecute = true;
                MyProc.StartInfo.RedirectStandardError = false;
                MyProc.StartInfo.RedirectStandardInput = false;
                MyProc.StartInfo.RedirectStandardOutput = false;
                MyProc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;


                //MyProc.StartInfo.Arguments = @" RENAMECOMPUTER " + oldname + @" /NewName:" + newname + @" /UserD:" + m_domain_admin + @" /PasswordD:" + m_domain_admin_password + @" /UserO:" + p_username + @" /PasswordO:" + p_password + @" /Force";
                MyProc.StartInfo.Arguments = oldname + @" " + newname + @" " + p_username + @" " + p_password + @" " + p_username + @" " + p_password;
                //MyProc.StartInfo.FileName = @"NETDOM RENAMECOMPUTER " + oldname + @" /NewName:" + newname + @" /UserD:" + m_domain_admin + @" /PasswordD:" + m_domain_admin_password + @" /UserO:" + p_username + @" /PasswordO:" + p_password + @" /Force";
                
                MyProc.Start();
                MyProc.WaitForExit();
                MyProc.Close();
            }
            catch (Exception e)
            {
                String msg = e.Message;
                String stacktrace = e.StackTrace;
                //StreamReader stdout = MyProc.StandardOutput;
                rc = false;
            }

            return rc;

        }


        public Boolean renameMachine(String oldname, String newname)
        {
            //Current settings work!
            if (String.IsNullOrEmpty(m_locationOfNetdomScript))
            {
                return false;
            }
            if (String.IsNullOrEmpty(m_domain_admin))
            {
                return false;
            }
            if (String.IsNullOrEmpty(m_domain_admin_password))
            {
                return false;
            }
            if (String.IsNullOrEmpty(m_PcAdministrator))
            {
                return false;
            }
            if (String.IsNullOrEmpty(m_PcAdministratorPassword))
            {
                return false;
            }

            Boolean rc = true;
            Process MyProc = new Process();

            try
            {

                MyProc.StartInfo.WorkingDirectory = m_locationOfNetdomScript;
                MyProc.StartInfo.FileName = "rename_netdom.bat";
                MyProc.StartInfo.UseShellExecute = true;
                MyProc.StartInfo.RedirectStandardError = false;
                MyProc.StartInfo.RedirectStandardInput = false;
                MyProc.StartInfo.RedirectStandardOutput = false;
                MyProc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;


                MyProc.StartInfo.Arguments = oldname + @" " + newname + @" " + m_domain_admin + @" " + m_domain_admin_password + @" " + m_PcAdministrator + @" " + m_PcAdministratorPassword;

                MyProc.Start();
                MyProc.WaitForExit();
                MyProc.Close();
            }
            catch (Exception e)
            {
                m_error_msg = e.Message;
                m_stacktrace = e.StackTrace;
                rc = false;
            }

            return rc;

        }

        public Boolean renameMachineNoScript(String oldname, String newname)
        {
            //Current settings work!
            if (String.IsNullOrEmpty(m_domain_admin))
            {
                return false;
            }
            if (String.IsNullOrEmpty(m_domain_admin_password))
            {
                return false;
            }
            if (String.IsNullOrEmpty(m_PcAdministrator))
            {
                return false;
            }
            if (String.IsNullOrEmpty(m_PcAdministratorPassword))
            {
                return false;
            }

            Boolean rc = true;
            Process MyProc = new Process();

            try
            {

                MyProc.StartInfo.WorkingDirectory = @"C:\\Program Files\\Support Tools";
                MyProc.StartInfo.FileName = "netdom.exe";
                MyProc.StartInfo.UseShellExecute = true;
                MyProc.StartInfo.RedirectStandardError = false;
                MyProc.StartInfo.RedirectStandardInput = false;
                MyProc.StartInfo.RedirectStandardOutput = false;
                MyProc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;


                MyProc.StartInfo.Arguments = @" RENAMECOMPUTER " + oldname + @" /NewName:" + newname + @" /UserD:" + m_domain_admin + @" /PasswordD:" + m_domain_admin_password + @" /UserO:" + m_PcAdministrator + @" /PasswordO:" + m_PcAdministratorPassword + @" /Force";

                MyProc.Start();
                MyProc.WaitForExit();
                MyProc.Close();
            }
            catch (Exception e)
            {
                m_error_msg = e.Message;
                m_stacktrace = e.StackTrace;
                rc = false;
            }

            return rc;

        }

        public void LastLogonForUser(string username, string domain)
        {
            DirectoryContext context =
              new DirectoryContext(
              DirectoryContextType.Domain,
              domain
              );

            DateTime latestLogon = DateTime.MinValue;
            string servername = null;

            DomainControllerCollection dcc =
              DomainController.FindAll(context);

            foreach (DomainController dc in dcc)
            {
                DirectorySearcher ds;

                using (dc)
                using (ds = dc.GetDirectorySearcher())
                {
                    ds.Filter = String.Format(
                      "(sAMAccountName={0})",
                      username
                      );
                    ds.PropertiesToLoad.Add("lastLogon");
                    ds.SizeLimit = 1;

                    SearchResult sr = ds.FindOne();

                    if (sr != null)
                    {
                        DateTime lastLogon = DateTime.MinValue;
                        if (sr.Properties.Contains("lastLogon"))
                        {
                            lastLogon = DateTime.FromFileTime(
                              (long)sr.Properties["lastLogon"][0]
                              );
                        }

                        if (DateTime.Compare(lastLogon, latestLogon) > 0)
                        {
                            latestLogon = lastLogon;
                            servername = dc.Name;
                        }
                    }
                }
            }
        }

        public void getLastLoginDataForMachine(String machineName)
        {
            DirectoryEntry dirs = new DirectoryEntry("WinNT://" + machineName);
            //DirectoryEntry dirs = new DirectoryEntry("LDAP://CN=" + machineName);

            if (null == dirs)
            {
                return;
            }

            foreach (DirectoryEntry de in dirs.Children)
            {
                if (de.SchemaClassName == "User")
                {
                    LastLogonInfo li = new LastLogonInfo();


                    if (de.Properties["Name"].Value != null)
                    {
                        String lastUsername = de.Properties["Name"].Value.ToString();
                        li.m_username = lastUsername;

                        if (de.Properties["lastLogin"].Value != null)
                        {
                            DateTime lastTimeStamp = (DateTime)de.Properties["lastLogin"].Value;
                            li.m_lastLogon = lastTimeStamp;
                        }

                        if (null != de.Properties["userAccountControl"].Value)
                        {
                            Int32 val;
                            val = (Int32)de.Properties["userAccountControl"].Value;
                            Boolean userEnabled = ((val & 2) <= 0);
                            li.m_enabled = userEnabled;
                        }
                        else
                        {
                            li.m_enabled = true;
                        }
                    }

                    m_lastLogons.Add(li);

                }
            }

        }

        public void getLastLoginEventsForMachine(String machineName)
        {
            if (String.IsNullOrEmpty(machineName))
            {
                return;
            }

            ManagementScope scope;
            ManagementObjectSearcher searcher;
            ManagementObjectCollection queryCollection;
            ConnectionOptions options = new ConnectionOptions();

            String localMachineName = null;
            localMachineName = Environment.MachineName;

            if (!localMachineName.ToUpper().Equals(machineName.ToUpper()))
            {
                options.Username = m_domain_admin;
                options.Password = m_domain_admin_password;
                options.Authentication = AuthenticationLevel.PacketPrivacy;
            }

            options.EnablePrivileges = true;
            options.Impersonation = ImpersonationLevel.Impersonate;
 
            scope = new ManagementScope("\\\\" + machineName + "\\root\\cimv2", options);
            scope.Connect();
 
            //SelectQuery query = new SelectQuery("select * from Win32_NTLogEvent where Logfile = 'System' and EventCode = 10 and SourceName = 'Print' and Type = 'information' and timegenerated >20081020 and timegenerated <20081025");
            //String queryStr = "select * from Win32_NTLogEvent where Logfile = 'Security' and EventCode = 528 and Type = 'SuccessA' and timegenerated > ";
            //Below works:
            //String queryStr = "select * from Win32_NTLogEvent where Logfile = 'Security' and EventIdentifier=528 and timegenerated >= '";
            //String queryStr = "select * from Win32_NTLogEvent where Logfile = 'Security' and eventType='4' and EventCode=528 and timegenerated >= '";
            //String queryStr = "select * from Win32_NTLogEvent where Logfile = 'Security' and EventCode='528' and timegenerated >= '";
            //String queryStr = "select * from Win32_NTLogEvent where Logfile = 'Security' and EventCode='528'";
            String queryStr = "select * from Win32_NTLogEvent where Logfile = 'Security' and TimeGenerated >= '";
            SelectQuery query = null;
            StringBuilder filterDate = new StringBuilder();
            TimeSpan thirtyDays = new TimeSpan(30, 0, 0, 0);
            DateTime thirtyDaysAgo = DateTime.Now.Subtract(thirtyDays);
            filterDate.Append(thirtyDaysAgo.Year);
            if (thirtyDaysAgo.Month < 10)
            {
                filterDate.Append("0");
            }
            filterDate.Append(thirtyDaysAgo.Month);
            if (thirtyDaysAgo.Day < 10)
            {
                filterDate.Append("0");
            }
            filterDate.Append(thirtyDaysAgo.Day);
            if (thirtyDaysAgo.Hour < 10)
            {
                filterDate.Append("0");
            }
            filterDate.Append(thirtyDaysAgo.Hour);
            if (thirtyDaysAgo.Minute < 10)
            {
                filterDate.Append("0");
            }
            filterDate.Append(thirtyDaysAgo.Minute);
            if (thirtyDaysAgo.Second < 10)
            {
                filterDate.Append("0");
            }
            filterDate.Append(thirtyDaysAgo.Second);
            filterDate.Append(".000000-360'");
            queryStr += filterDate.ToString();
            query = new SelectQuery(queryStr);
           
            searcher = new ManagementObjectSearcher(scope, query);
 
 
            try
            {
                queryCollection = searcher.Get();

                foreach (ManagementObject obj in queryCollection)
                {

                    UInt16 currEventCode = (UInt16)obj.GetPropertyValue("EventCode");
                    UInt16 currCategory = (UInt16)obj.GetPropertyValue("Category");
                    String currCategoryString = obj.GetPropertyValue("CategoryString").ToString();

                    //if (currEventCode == 528 && currCategory == 2)
                    if (currCategoryString.Contains("Logon"))
                    {
                        LastLogonInfo li = new LastLogonInfo();
                        String user = obj.GetPropertyValue("User").ToString();

                        if (user.Contains("NT AUTHORITY"))
                        {
                            continue;
                        }

                        String lastLogonDate = obj.GetPropertyValue("TimeGenerated").ToString();
                        li.m_username = user;
                        //li.m_lastLogon = (DateTime)obj.GetPropertyValue("TimeGenerated");
                        //li.m_lastLogonString = lastLogonDate;
                        li.m_lastLogon = convertEventTime(lastLogonDate);
                        m_lastLogons.Add(li);
                    }
                }

            }
            catch (Exception e)
            {
                //MessageBox.Show(e.Message);
                LastLogonInfo li = new LastLogonInfo();
                li.m_errorMsg = e.Message;
                li.m_errorDump = e.StackTrace;
                m_lastLogons.Add(li);

                return;
 
            }
 

        }

        public DateTime convertEventTime(String eventTime)
        {
            DateTime answer;
            if (String.IsNullOrEmpty(eventTime))
            {
                answer = DateTime.Now;
                return answer;
            }

            Int32 YYYY = Convert.ToInt32(eventTime.Substring(0, 4));
            Int32 MM = Convert.ToInt32(eventTime.Substring(4, 2));
            Int32 DD = Convert.ToInt32(eventTime.Substring(6, 2));
            Int32 hh = Convert.ToInt32(eventTime.Substring(8, 2));
            Int32 mm = Convert.ToInt32(eventTime.Substring(10, 2));
            Int32 ss = Convert.ToInt32(eventTime.Substring(12, 2));

            answer = new DateTime(YYYY, MM, DD, hh, mm, ss);

            return answer;

        }

        public Boolean removeUserByDirectoryServices(String machineName, String pcAdministrator, String pcAdministratorPassword)
        {
            Boolean rc = false;

            try
            {
                String connString = "WinNT://" + machineName;
                DirectoryEntry de = new DirectoryEntry(connString, pcAdministrator, pcAdministratorPassword);
                //DirectoryEntry user = de.Children.Add(m_PcAdministrator, "user");
                //user.Invoke("SetPassword", new Object[] { m_PcAdministratorPassword });

                DirectoryEntry adminGroup = de.Children.Find("Administrators", "group");
                DirectoryEntry user = de.Children.Find(m_PcAdministrator, "user");

                if (null != adminGroup)
                {
                    adminGroup.Invoke("Remove", new Object[] { user.Path.ToString() });
                }


                de.RefreshCache();
                
                de.Children.Remove(user);

                de.CommitChanges();
                de.Close();

                rc = true;


            }
            catch (Exception e)
            {
                String msg = e.Message;
                String stacktrace = e.StackTrace;
            }

            return rc;

        }

        
    }
}
